import * as clouddb from '@agconnect/database-server';
import { t_mall_sku as mallSkuInfo } from './models/t_mall_sku';
import { t_mall_spu as mallSpuInfo } from './models/t_mall_spu';
import { t_mall_spu_attr as mallSpuAttrInfo } from './models/t_mall_spu_attr';
import { t_mall_order as mallOrderInfo } from './models/t_mall_order';
import { t_mall_user_addr as mallUserAddr } from './models/t_mall_user_addr';
import { t_mall_shopcart as shopCartInfo } from './models/t_mall_shopcart';
import * as agconnect from '@agconnect/common-server';
import { CloudDBZone } from '@agconnect/database-server';

const ZONE_NAME = "shopping";

export class CloudDBZoneWrapper {
    logger;
    cloudDbZone:CloudDBZone;

    constructor(credential, logger) {
        this.logger = logger;
        try {
            // 初始化AGCClient
            logger.info("begin to init agcClient");
            let agcClient;
            try {
                agcClient = agconnect.AGCClient.getInstance();
            } catch {
                agconnect.AGCClient.initialize(credential);
                agcClient = agconnect.AGCClient.getInstance();
            }
            // 初始化AGConnectCloudDB实例
            logger.info("begin to init clouddb");
            let cloudDbInstance;
            try {
                cloudDbInstance = clouddb.AGConnectCloudDB.getInstance(agcClient);
            } catch {
                clouddb.AGConnectCloudDB.initialize(agcClient);
                cloudDbInstance = clouddb.AGConnectCloudDB.getInstance(agcClient);
            }
            // 创建CloudDBZoneConfig配置对象，并设置云侧CloudDB zone名称，打开Cloud DB zone实例
            const cloudDBZoneConfig = new clouddb.CloudDBZoneConfig(ZONE_NAME);
            this.cloudDbZone = cloudDbInstance.openCloudDBZone(cloudDBZoneConfig);
        } catch (err) {
            logger.error("init CloudDBZoneWrapper error: " + err);
        }
    }

    // 查询商品信息
    async queryGoodsData(pageSize, currentPage) {
        // 定义数组来存储查询结果
        let mallSkuInfoList = []; // 存储SKU信息的数组
        let mallSpuInfoList = []; // 存储SPU信息的数组
        let mallSpuAttrInfoList = []; // 存储商品属性信息的数组
        let result = []; // 最终的商品列表结果

        // 检查cloudDbZone是否已初始化，如果没有则记录错误日志
        if (!this.cloudDbZone) {
            this.logger.error("CloudDBClient is null, try re-initialize it");
        }

        // 计算查询的起始ID，用于分页
        let startId = Number(pageSize) * Number(currentPage) - pageSize + 1;

        // 创建SKU和SPU查询对象，并设置起始ID
        let skuInfo = new mallSkuInfo();
        let spuInfo = new mallSpuInfo();
        skuInfo.setSku_id(startId);
        spuInfo.setSpu_id(startId);

        // 构建SKU查询条件，按sku_id升序排序，并设置查询的起始记录和限制返回数量
        const mallSkuInfoQuery = clouddb.CloudDBZoneQuery.where(mallSkuInfo)
            .orderByAsc("sku_id")
            .startAt(skuInfo)
            .limit(pageSize);

        // 构建SPU查询条件，按spu_id升序排序，并设置查询的起始记录和限制返回数量
        const mallSpuInfoQuery = clouddb.CloudDBZoneQuery.where(mallSpuInfo)
            .orderByAsc("spu_id")
            .startAt(spuInfo)
            .limit(pageSize);

        // 构建商品属性查询条件，不设置排序和起始记录，查询全部属性信息
        const mallSpuAttrInfoQuery = clouddb.CloudDBZoneQuery.where(mallSpuAttrInfo);

        // 异步执行查询操作，获取SKU、SPU和商品属性信息
        const mallSkuInfoResp = await this.cloudDbZone.executeQuery(mallSkuInfoQuery);
        const mallSpuInfoResp = await this.cloudDbZone.executeQuery(mallSpuInfoQuery);
        const mallSpuAttrInfoResp = await this.cloudDbZone.executeQuery(mallSpuAttrInfoQuery);

        // 将查询结果转换为对象数组
        mallSkuInfoList = mallSkuInfoResp.getSnapshotObjects();
        mallSpuInfoList = mallSpuInfoResp.getSnapshotObjects();
        mallSpuAttrInfoList = mallSpuAttrInfoResp.getSnapshotObjects();

        // 调用辅助方法，将查询到的SKU、SPU和商品属性信息组合成完整的商品列表
        result = this.getQueryResult(mallSpuInfoList, mallSkuInfoList, mallSpuAttrInfoList);

        // 记录查询成功的日志
        this.logger.info("query GoodsList success ");

        // 返回最终的商品列表
        return result;
    }

    /**
     * 将查询到的SKU、SPU和商品属性信息组合成完整的商品列表
     * @param {Array} spuList - 查询到的SPU信息列表
     * @param {Array} skuList - 查询到的SKU信息列表
     * @param {Array} spuAttrList - 查询到的商品属性信息列表
     * @returns {Array} - 完整的商品列表
     * 示例：
     * 传入的参数：
     * // 模拟的SPU列表
     let spuList = [
     { spu_id: 101, name: "苹果手机", desc: "新款苹果手机", price: 5999, category_id: 1, pic_url: "http://example.com/pic1.jpg" },
     { spu_id: 102, name: "华为手机", desc: "新款华为手机", price: 3999, category_id: 2, pic_url: "http://example.com/pic2.jpg" }
     ];

     // 模拟的SKU列表
     let skuList = [
     { sku_id: 201, spu_id: 101, pic_url: "http://example.com/detail1.jpg", attrs: JSON.stringify({ attr_ids: [1, 2] }) },
     { sku_id: 202, spu_id: 102, pic_url: "http://example.com/detail2.jpg", attrs: JSON.stringify({ attr_ids: [3] }) }
     ];

     // 模拟的商品属性列表
     let spuAttrList = [
     { attr_id: 1, name: "颜色", attr_vals: JSON.stringify(["黑色", "白色"]) },
     { attr_id: 2, name: "内存", attr_vals: JSON.stringify(["64GB", "128GB"]) },
     { attr_id: 3, name: "颜色", attr_vals: JSON.stringify(["红色"]) }
     ];

     输出：
     [
     {
     "detail_pic_url": "http://example.com/detail1.jpg",
     "attr_list": "[{\"name\":\"颜色\",\"value\":[\"黑色\",\"白色\"]},{\"name\":\"内存\",\"value\":[\"64GB\",\"128GB\"]}]",
     "name": "苹果手机",
     "desc": "新款苹果手机",
     "price": 5999,
     "spu_id": 101,
     "category_id": 1,
     "pic_url": "http://example.com/pic1.jpg"
     },
     {
     "detail_pic_url": "http://example.com/detail2.jpg",
     "attr_list": "[{\"name\":\"颜色\",\"value\":[\"红色\"]}]",
     "name": "华为手机",
     "desc": "新款华为手机",
     "price": 3999,
     "spu_id": 102,
     "category_id": 2,
     "pic_url": "http://example.com/pic2.jpg"
     }
     ]
     */
    getQueryResult(spuList, skuList, spuAttrList) {
        // 初始化结果数组，用于存储最终的商品信息
        let result = [];

        // 遍历SKU列表
        skuList.forEach((skuElm) => {
            // 通过SKU的spu_id查找对应的SPU信息索引
            let spuIdIndex = spuList.findIndex((elm) => elm.spu_id === skuElm.spu_id);

            // 初始化SKU结果对象，包含商品图片URL
            let skuElmResult = {
                detail_pic_url: skuElm.pic_url || null,
            };

            // 初始化属性列表数组
            let attr_list = [];

            // 解析SKU的属性字符串为数组
            let attrsArr = JSON.parse(skuElm.attrs);

            // 遍历属性数组，查找对应的商品属性信息
            attrsArr.attr_ids.forEach((attrItem) => {
                let attrElm = spuAttrList.find((elm) => attrItem == elm.attr_id);
                attr_list.push({
                    name: attrElm.name, // 属性名称
                    value: JSON.parse(attrElm.attr_vals), // 属性值
                });
            });

            // 将属性列表转换为字符串，并初始化SPU属性结果对象
            let spuAttrElmResult = {
                attr_list: JSON.stringify(attr_list),
            };

            // 初始化SPU结果对象，包含商品名称、描述、价格等信息
            let spuElmResult = {
                name: spuList[spuIdIndex]?.name || null,
                desc: spuList[spuIdIndex]?.desc || null,
                price: spuList[spuIdIndex]?.price || null,
                spu_id: spuList[spuIdIndex]?.spu_id || null,
                category_id: spuList[spuIdIndex]?.category_id || null,
                pic_url: spuList[spuIdIndex]?.pic_url || null,
            };

            // 将SKU结果对象、SPU结果对象和SPU属性结果对象合并，并添加到结果数组中
            result.push(Object.assign(skuElmResult, spuElmResult, spuAttrElmResult));
        });

        // 返回最终的商品列表
        return result;
    }


    // 搜索商品信息
    async searchGoodsData(keyword) {
        // 定义数组来存储查询结果
        let mallSkuInfoList = []; // 存储SKU信息的数组
        let mallSpuInfoList = []; // 存储SPU信息的数组
        let mallSpuAttrInfoList = []; // 存储商品属性信息的数组
        let result = []; // 存储最终搜索结果的数组

        // 检查cloudDbZone是否已初始化，如果没有则记录错误日志
        if (!this.cloudDbZone) {
            this.logger.error("CloudDBClient is null, try re-initialize it");
        }

        // 构建SKU查询条件，查询所有SKU信息
        const mallSkuInfoQuery = clouddb.CloudDBZoneQuery.where(mallSkuInfo);

        // 构建SPU查询条件，搜索包含指定关键字的商品名称
        const mallSpuInfoQuery = clouddb.CloudDBZoneQuery.where(mallSpuInfo)
            .contains("name", keyword);

        // 构建商品属性查询条件，查询所有商品属性信息
        const mallSpuAttrInfoQuery = clouddb.CloudDBZoneQuery.where(mallSpuAttrInfo);

        try {
            // 异步执行查询操作，获取SKU、SPU和商品属性信息
            const mallSkuInfoResp = await this.cloudDbZone.executeQuery(mallSkuInfoQuery);
            const mallSpuInfoResp = await this.cloudDbZone.executeQuery(mallSpuInfoQuery);
            const mallSpuAttrInfoResp = await this.cloudDbZone.executeQuery(mallSpuAttrInfoQuery);

            // 将查询结果转换为对象数组
            mallSkuInfoList = mallSkuInfoResp.getSnapshotObjects();
            mallSpuInfoList = mallSpuInfoResp.getSnapshotObjects();
            mallSpuAttrInfoList = mallSpuAttrInfoResp.getSnapshotObjects();

            // 调用辅助方法，将查询到的SKU、SPU和商品属性信息组合成搜索结果列表
            result = this.getSearchResult(mallSpuInfoList, mallSkuInfoList, mallSpuAttrInfoList);

            // 记录搜索成功的日志
            this.logger.info("get search result success");
        } catch (error) {
            // 如果搜索过程中发生错误，记录错误日志
            this.logger.error("get search result failed");
        }

        // 返回搜索结果
        return result;
    }

    /**
     * 将搜索结果中的 SPU、SKU 和商品属性信息组合成一个统一的格式。
     * @param {Array} spuList - 包含 SPU 信息的数组。
     * @param {Array} skuList - 包含 SKU 信息的数组。
     * @param {Array} spuAttrList - 包含商品属性信息的数组。
     * @returns {Array} - 组合后的商品信息数组。
     */
     getSearchResult(spuList, skuList, spuAttrList) {
        let result = []; // 初始化结果数组

        // 遍历 SPU 列表
        spuList.forEach((spuEle) => {
            // 通过 SPU 的 spu_id 在 SKU 列表中找到对应的 SKU 索引
            let skuIndex = skuList.findIndex((elm) => elm.spu_id === spuEle.spu_id);

            // 初始化 SKU 结果对象，包含商品图片 URL
            let skuElmResult = {
                pic_url: skuList[skuIndex].pic_url || null,
            };

            // 初始化属性列表数组
            let attr_list = [];

            // 解析 SKU 的属性字符串为数组
            let attrsArr = JSON.parse(skuList[skuIndex].attrs);

            // 遍历属性数组，找到对应的商品属性信息，并添加到属性列表中
            attrsArr.attr_ids.forEach((attrItem) => {
                let attrElm = spuAttrList.find((elm) => attrItem == elm.attr_id);
                attr_list.push({
                    name: attrElm.name, // 属性名称
                    value: JSON.parse(attrElm.attr_vals), // 属性值
                });
            });

            // 将属性列表转换为字符串，并初始化 SPU 属性结果对象
            let spuAttrElmResult = {
                attr_list: JSON.stringify(attr_list),
            };

            // 初始化 SPU 结果对象，包含商品名称、描述、价格等信息
            let spuElmResult = {
                name: spuEle?.name || null, // 商品名称
                desc: spuEle?.desc || null, // 商品描述
                price: spuEle?.price || null, // 商品价格
                spu_id: spuEle?.spu_id || null, // SPU ID
                category_id: spuEle?.category_id || null, // 商品分类 ID
                detail_pic_url: spuEle?.pic_url || null, // 商品详细图片 URL
            };

            // 将 SKU 结果对象、SPU 结果对象和 SPU 属性结果对象合并，并添加到结果数组中
            result.push(Object.assign(skuElmResult, spuElmResult, spuAttrElmResult));
        });

        // 返回组合后的商品信息数组
        return result;
    }

    /**
     * 通过商品的标准产品单位 ID 查询商品的详细信息。
     * @param {string} spuId - 商品的标准产品单位 ID。
     * @returns {Object} - 商品的详细信息。
     */
    async queryGoodsDataById(spuId) {
        let mallSkuInfoObj = new mallSkuInfo(); // 初始化 SKU 对象
        let mallSpuInfoObj = new mallSpuInfo(); // 初始化 SPU 对象
        let mallSpuAttrInfoArr = []; // 初始化商品属性数组

        // 检查 CloudDBZone 实例是否存在
        if (!this.cloudDbZone) {
            this.logger.error("CloudDBClient is null, try re-initialize it");
        }

        // 检查传入的 spuId 是否为空
        if (!spuId) {
            this.logger.error("spuId is empty");
            return;
        }

        // 构建 SKU 查询条件，筛选 spu_id 与传入 spuId 相等的记录
        const mallSkuInfoQuery = clouddb.CloudDBZoneQuery.where(mallSkuInfo)
            .equalTo("spu_id", spuId);

        // 构建 SPU 查询条件，筛选 spu_id 与传入 spuId 相等的记录
        const mallSpuInfoQuery = clouddb.CloudDBZoneQuery.where(mallSpuInfo)
            .equalTo("spu_id", spuId);

        // 构建商品属性查询条件，查询所有商品属性信息
        const mallSpuAttrInfoQuery = clouddb.CloudDBZoneQuery.where(mallSpuAttrInfo);

        try {
            // 异步执行 SKU 查询操作
            const mallSkuInfoResp = await this.cloudDbZone.executeQuery(mallSkuInfoQuery);
            // 异步执行 SPU 查询操作
            const mallSpuInfoResp = await this.cloudDbZone.executeQuery(mallSpuInfoQuery);
            // 异步执行商品属性查询操作
            const mallSpuAttrInfoResp = await this.cloudDbZone.executeQuery(mallSpuAttrInfoQuery);

            // 从查询响应中获取 SKU 对象
            mallSkuInfoObj = mallSkuInfoResp.getSnapshotObjects()[0];
            // 从查询响应中获取 SPU 对象
            mallSpuInfoObj = mallSpuInfoResp.getSnapshotObjects()[0];
            // 获取所有商品属性对象
            mallSpuAttrInfoArr = mallSpuAttrInfoResp.getSnapshotObjects();

            // 记录查询成功的日志
            this.logger.info("query GoodsDetail success ");
        } catch (error) {
            // 如果查询过程中发生错误，记录错误日志
            this.logger.error("query GoodsDetail failed ");
        }

        // 解析 SKU 对象中的属性 ID 字符串
        let { attr_ids } = JSON.parse(mallSkuInfoObj.attrs);
        let attr_list = {}; // 初始化属性列表对象

        // 遍历属性 ID 数组，获取对应的属性值
        attr_ids.forEach((elm) => {
            let attrIdItem = mallSpuAttrInfoArr.find((item) => item.attr_id == elm);
            attr_list[attrIdItem.name] = attrIdItem.attr_vals;
        });

        // 返回商品的详细信息对象
        return {
            spu_id: spuId,
            name: mallSpuInfoObj.name,
            desc: mallSpuInfoObj.desc,
            price: mallSpuInfoObj.price,
            pic_url: mallSpuInfoObj.pic_url,
            category_id: mallSpuInfoObj.category_id,
            detail_pic_url: mallSpuInfoObj.pic_url,
            attr_list,
        };
    }

    // 统计商品条目
    async queryGoodsCount() {

        if (!this.cloudDbZone) {
            this.logger.error("CloudDBClient is null, try re-initialize it");
        }

        let spuInfo = new mallSpuInfo();

        const mallSpuInfoQuery = clouddb.CloudDBZoneQuery.where(mallSpuInfo);
        const spu_count = await this.cloudDbZone.executeCountQuery(mallSpuInfoQuery,'spu_id')

        this.logger.info("queryGoodsCount success ");
        return spu_count;
    }
};
